import shutil

print(dir(shutil))
"""
'chown', 'collections', 'copy', 'copy2', 'copyfile', 'copyfileobj', 'copymode', 'copystat', 'copytree', 'disk_usage', 
'errno', 'fnmatch', 'get_archive_formats', 'get_terminal_size', 'get_unpack_formats', 'ignore_patterns', 'make_archive', 
'move', 'nt', 'os', 'posix', 'register_archive_format', 'register_unpack_format', 'rmtree', 'stat', 'sys', 
'unpack_archive', 'unregister_archive_format', 'unregister_unpack_format', 'which'
"""

# !/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
涵盖了shutil模块的所有重要方法：
文件复制（copy, copy2, copyfile 等）
目录操作（copytree, move, rmtree 等）
归档压缩（make_archive, unpack_archive 等）
其他实用功能（disk_usage, which 等）
"""

import shutil
import os
import tempfile
from datetime import datetime


def print_separator(title):
    """打印分隔线，用于区分不同功能区域"""
    print(f"\n{'=' * 20} {title} {'=' * 20}")


def demo_file_copy_operations():
    """演示文件复制相关操作"""
    print_separator("文件复制相关方法")

    # 创建临时文件用于演示
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
        f.write("这是一个测试文件，用于演示shutil的复制功能")
        src_file = f.name
        print(f"创建临时测试文件: {src_file}")

    # 1. shutil.copy: 复制文件内容和权限
    dst_copy = src_file + "_copy"
    shutil.copy(src_file, dst_copy)
    print(f"使用copy复制到: {dst_copy}")

    # 2. shutil.copy2: 复制文件内容和元数据
    dst_copy2 = src_file + "_copy2"
    shutil.copy2(src_file, dst_copy2)
    print(f"使用copy2复制到: {dst_copy2}")
    print(f"原文件修改时间: {datetime.fromtimestamp(os.stat(src_file).st_mtime)}")
    print(f"copy2复制文件修改时间: {datetime.fromtimestamp(os.stat(dst_copy2).st_mtime)}")

    # 3. shutil.copyfile: 仅复制文件内容
    dst_copyfile = src_file + "_copyfile"
    shutil.copyfile(src_file, dst_copyfile)
    print(f"使用copyfile复制到: {dst_copyfile}")

    # 4. shutil.copyfileobj: 通过文件对象复制
    dst_copyfileobj = src_file + "_copyfileobj"
    with open(src_file, 'rb') as fsrc, open(dst_copyfileobj, 'wb') as fdst:
        shutil.copyfileobj(fsrc, fdst, length=1024)  # 使用1KB缓冲区
    print(f"使用copyfileobj复制到: {dst_copyfileobj}")

    # 5. shutil.copymode: 仅复制权限
    dst_copymode = src_file + "_copymode"
    with open(dst_copymode, 'w') as f:
        f.write("测试copymode的文件")
    shutil.copymode(src_file, dst_copymode)
    print(f"使用copymode复制权限到: {dst_copymode}")

    # 6. shutil.copystat: 复制元数据
    dst_copystat = src_file + "_copystat"
    with open(dst_copystat, 'w') as f:
        f.write("测试copystat的文件")
    shutil.copystat(src_file, dst_copystat)
    print(f"使用copystat复制元数据到: {dst_copystat}")

    # 清理临时文件
    for f in [dst_copy, dst_copy2, dst_copyfile, dst_copyfileobj, dst_copymode, dst_copystat, src_file]:
        if os.path.exists(f):
            os.remove(f)


def demo_directory_operations():
    """演示目录操作相关方法"""
    print_separator("目录操作相关方法")

    # 创建临时目录
    temp_dir = tempfile.mkdtemp()
    print(f"创建临时目录: {temp_dir}")

    # 在临时目录中创建一些测试文件和子目录
    subdir = os.path.join(temp_dir, "subdir")
    os.makedirs(subdir)
    test_file = os.path.join(subdir, "test.txt")
    with open(test_file, 'w') as f:
        f.write("目录测试文件")

    # 1. shutil.copytree: 递归复制目录
    copy_dir = temp_dir + "_copy"
    # 忽略.txt文件
    shutil.copytree(temp_dir, copy_dir, ignore=shutil.ignore_patterns("*.txt"))
    print(f"使用copytree复制目录到: {copy_dir}")
    print(f"复制的目录内容: {os.listdir(copy_dir)}")

    # 2. shutil.move: 移动文件或目录
    move_dir = temp_dir + "_moved"
    shutil.move(temp_dir, move_dir)
    print(f"使用move移动目录到: {move_dir}")

    # 3. shutil.rmtree: 递归删除目录
    shutil.rmtree(copy_dir)
    shutil.rmtree(move_dir)
    print(f"使用rmtree删除了测试目录")


def demo_archive_operations():
    """演示归档和压缩相关方法"""
    print_separator("归档与压缩相关方法")

    # 创建临时目录和文件用于归档
    temp_dir = tempfile.mkdtemp()
    for i in range(3):
        with open(os.path.join(temp_dir, f"file{i}.txt"), 'w') as f:
            f.write(f"这是归档测试文件 {i}")

    # 1. 查看支持的归档格式
    print("支持的归档格式:")
    for fmt in shutil.get_archive_formats():
        print(f"  - {fmt[0]}: {fmt[1]}")

    print("\n支持的解压缩格式:")
    for fmt in shutil.get_unpack_formats():
        print(f"  - {fmt[0]}: {fmt[1]}")

    # 2. shutil.make_archive: 创建归档文件
    archive_name = os.path.join(os.path.dirname(temp_dir), "test_archive")
    archive_format = "zip"  # 可以尝试 "tar", "gztar", "bztar" 等
    archive_path = shutil.make_archive(archive_name, archive_format, root_dir=temp_dir)
    print(f"\n使用make_archive创建归档: {archive_path}")

    # 3. shutil.unpack_archive: 解压缩归档
    extract_dir = temp_dir + "_extracted"
    os.makedirs(extract_dir)
    shutil.unpack_archive(archive_path, extract_dir)
    print(f"使用unpack_archive解压缩到: {extract_dir}")
    print(f"解压缩的内容: {os.listdir(extract_dir)}")

    # 清理临时文件
    shutil.rmtree(temp_dir)
    shutil.rmtree(extract_dir)
    os.remove(archive_path)


def demo_other_functions():
    """演示其他实用方法"""
    print_separator("其他实用方法")

    # 1. shutil.disk_usage: 获取磁盘使用情况
    try:
        # 对于Windows系统，可以使用"C:"代替
        usage = shutil.disk_usage("/")
        print("磁盘使用情况:")
        print(f"  总空间: {usage.total / (1024 ** 3):.2f} GB")
        print(f"  已使用: {usage.used / (1024 ** 3):.2f} GB")
        print(f"  剩余空间: {usage.free / (1024 ** 3):.2f} GB")
    except PermissionError:
        print("无法获取磁盘使用情况（权限不足）")

    # 2. shutil.which: 查找可执行程序路径
    print("\n可执行程序路径:")
    python_path = shutil.which("python") or shutil.which("python3")
    print(f"  Python: {python_path}")

    if os.name == "nt":  # Windows系统
        notepad_path = shutil.which("notepad.exe")
        print(f"  记事本: {notepad_path}")
    else:  # Unix/Linux系统
        ls_path = shutil.which("ls")
        print(f"  ls命令: {ls_path}")


def explain_shutil_attributes():
    """解释shutil模块的重要属性"""
    print_separator("shutil模块重要属性")

    print("1. shutil.os: 内部引用的os模块，用于基础文件操作")
    print(f"   示例: shutil.os.getcwd() 返回 {shutil.os.getcwd()}")

    print("\n2. shutil.sys: 内部引用的sys模块，用于系统相关操作")
    print(f"   示例: shutil.sys.platform 返回 {shutil.sys.platform}")

    print("\n3. shutil.errno: 错误码定义，用于处理文件操作异常")
    print(f"   示例: 文件未找到错误码: {shutil.errno.ENOENT}")

    print("\n4. shutil.stat: 引用stat模块，用于处理文件状态")
    print(f"   示例: 普通文件模式: {oct(shutil.stat.S_IFREG)}")

    print("\n5. shutil.ignore_patterns: 创建忽略规则的函数")
    print("   示例: shutil.ignore_patterns('*.pyc', '*.log') 可忽略编译文件和日志文件")


def main():
    """主函数，按顺序演示所有功能"""
    print("===== Python shutil模块详解与示例 =====")

    # 解释shutil模块的重要属性
    explain_shutil_attributes()

    # 演示文件复制相关操作
    demo_file_copy_operations()

    # 演示目录操作相关方法
    demo_directory_operations()

    # 演示归档和压缩相关方法
    demo_archive_operations()

    # 演示其他实用方法
    demo_other_functions()

    print("\n===== 所有演示完成 =====")


if __name__ == "__main__":
    main()
